package edu.calvin.djs32.cs214.interpreters.calculator;

import java.util.HashMap;
import java.util.Map;

import edu.calvin.cs214.hobbes2008.ApplicationTIR;
import edu.calvin.cs214.hobbes2008.HobbesTIR;
import edu.calvin.cs214.hobbes2008.HobbesTIRVisitor;
import edu.calvin.cs214.hobbes2008.IdentifierTIR;
import edu.calvin.cs214.hobbes2008.IfTIR;
import edu.calvin.cs214.hobbes2008.IntegerTIR;
import edu.calvin.cs214.hobbes2008.StringTIR;
import edu.calvin.cs214.hobbes2008.TupleTIR;
import edu.calvin.djs32.cs214.interpreters.calculator.primitives.AbsPrimitive;
import edu.calvin.djs32.cs214.interpreters.calculator.primitives.AddPrimitive;
import edu.calvin.djs32.cs214.interpreters.calculator.primitives.DividePrimitive;
import edu.calvin.djs32.cs214.interpreters.calculator.primitives.FactorialPrimitive;
import edu.calvin.djs32.cs214.interpreters.calculator.primitives.MaxPrimitive;
import edu.calvin.djs32.cs214.interpreters.calculator.primitives.MinPrimitive;
import edu.calvin.djs32.cs214.interpreters.calculator.primitives.MultiplyPrimitive;
import edu.calvin.djs32.cs214.interpreters.calculator.primitives.PowPrimitive;
import edu.calvin.djs32.cs214.interpreters.calculator.primitives.SqrtPrimitive;
import edu.calvin.djs32.cs214.interpreters.calculator.primitives.SquarePrimitive;
import edu.calvin.djs32.cs214.interpreters.calculator.primitives.SubtractPrimitive;

public class Calculator implements HobbesTIRVisitor<HobbesTIR>{
	public Map<IdentifierTIR, Primitive> myPrimitives;

	public Calculator(Map<IdentifierTIR, Primitive> prims) {
		myPrimitives = prims;
	}

	public Calculator() {
		  myPrimitives = new HashMap<IdentifierTIR, Primitive>();
		  myPrimitives.put(new IdentifierTIR("+"), new AddPrimitive());
		  myPrimitives.put(new IdentifierTIR("-"), new SubtractPrimitive());
		  myPrimitives.put(new IdentifierTIR("/"), new DividePrimitive());
		  myPrimitives.put(new IdentifierTIR("*"), new MultiplyPrimitive());
		  myPrimitives.put(new IdentifierTIR("abs"), new AbsPrimitive());
		  myPrimitives.put(new IdentifierTIR("max"), new MaxPrimitive());
		  myPrimitives.put(new IdentifierTIR("min"), new MinPrimitive());
		  myPrimitives.put(new IdentifierTIR("square"), new SquarePrimitive());
		  myPrimitives.put(new IdentifierTIR("sqrt"), new SqrtPrimitive());
		  myPrimitives.put(new IdentifierTIR("pow"), new PowPrimitive());
		  myPrimitives.put(new IdentifierTIR("!"), new FactorialPrimitive());
	}

	public HobbesTIR visitApplication(ApplicationTIR application) {

			HobbesTIR[] arguments = new HobbesTIR[application.getTuple().getLength()];
			for (int i = 0; i < application.getTuple().getLength(); i++){
				arguments[i] = (IntegerTIR) application.getTuple().getElement(i).accept(this);
			}
			Primitive primitiveRet = myPrimitives.get(application.getIdentifier());
			return primitiveRet.apply(arguments);
		
	}

	public HobbesTIR visitInteger(IntegerTIR integer) {
		return integer;
	}

	public HobbesTIR visitString(StringTIR string) {
		return string;
	}

	public HobbesTIR visitTuple(TupleTIR tuple) {
		return tuple;
	}

	public HobbesTIR visitIf(IfTIR ifExpression) {
		// TODO Auto-generated method stub
		return null;
	}

}
